package com.gwb.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.*;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import lombok.NonNull;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.io.*;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 无法流式返回
 */
public class MoonshotAiUtils {


    private static final String API_KEY = "";
    private static final String MODELS_URL = "https://api.moonshot.cn/v1/models";
    private static final String FILES_URL = "https://api.moonshot.cn/v1/files";
    private static final String ESTIMATE_TOKEN_COUNT_URL = "https://api.moonshot.cn/v1/tokenizers/estimate-token-count";
    private static final String CHAT_COMPLETION_URL = "https://api.moonshot.cn/v1/chat/completions";


    @Resource
    KimiClient kimiClient;

    public static String getModelList() {
        return getCommonRequest(MODELS_URL)
                .execute()
                .body();
    }

    /***
     * 上传文件
     * {"id":"cq99ijqtnn0t879b57fg","object":"file","bytes":133,
     *   "created_at":1720883535,"filename":"用户增长表.csv",
     *   purpose":"file-extract","status":"ok","status_details":""}
     * @param file
     * @return
     */
    public static String uploadFile(@NonNull File file) {
        return getCommonRequest(FILES_URL)
                .method(Method.POST)
                .header("purpose", "file-extract")
                .form("file", file)
                .execute()
                .body();
    }

    /***
     * 获取文件列表
     * {"object":"list","data":[{"id":"cq99ijqtnn0t879b57fg",
     * "object":"file","bytes":133,"created_at":1720883535,
     * "filename":"用户增长表.csv","purpose":"file-extract",
     * "status":"ok","status_details":""}]}
     * @return
     */
    public static String getFileList() {
        return getCommonRequest(FILES_URL)
                .execute()
                .body();
    }

    /***
     * 删除文件
     * {"deleted":true,"id":"cq99ijqtnn0t879b57fg","object":"file"}
     * @param fileId
     * @return
     */
    public static String deleteFile(@NonNull String fileId) {
        return getCommonRequest(FILES_URL + "/" + fileId)
                .method(Method.DELETE)
                .execute()
                .body();
    }

    /***
     * 获取文件信息详情
     * {"id":"cq99ijqtnn0t879b57fg","object":"file","bytes":133,
     * "created_at":1720883535,"filename":"用户增长表.csv",
     * "purpose":"file-extract","status":"ok","status_details":""}
     * @param fileId
     * @return
     */
    public static String getFileDetail(@NonNull String fileId) {
        return getCommonRequest(FILES_URL + "/" + fileId)
                .execute()
                .body();
    }

    /**
     * 获取文件内容
     * {"content":"时间: 2024.01.01\n增长用户数: 1\n: 时间: 2024.01.02\n
     * 增长用户数: 2\n: 时间: 2024.01.03\n增长用户数: 33\n: 时间: 2024.01.04\n
     * 增长用户数: 2\n: 时间: 2024.01.05\n增长用户数: 1\n: 时间: 2024.01.06\n
     * 增长用户数: 12\n: 时间: 2024.01.07\n增长用户数: 65\n: ",
     * "file_type":"application/vnd.ms-excel","filename":"用户增长表.csv","title":"","type":"file"}
     * @param fileId
     * @return
     */
    public static String getFileContent(@NonNull String fileId) {
        return getCommonRequest(FILES_URL + "/" + fileId + "/content")
                .execute()
                .body();
    }

    public static String estimateTokenCount(@NonNull String model, @NonNull List<Message> messages) {
        String requestBody = new JSONObject()
                .putOpt("model", model)
                .putOpt("messages", messages)
                .toString();
        return getCommonRequest(ESTIMATE_TOKEN_COUNT_URL)
                .method(Method.POST)
                .header(Header.CONTENT_TYPE, ContentType.JSON.getValue())
                .body(requestBody)
                .execute()
                .body();
    }
    public void getApiKey(){
        KimiClient kimiClient = (KimiClient)SpringUtil.getBean("kimiClient");
        System.out.println(kimiClient.getApiKey());
    }
    //在这个例子中，readFile 方法使用了 @SneakyThrows 注解，这意味着它可以抛出 IOException 而不需要在方法签名中声明它。Lombok 会在编译时自动处理这个异常。
    @SneakyThrows
    public static String doChat(@NonNull String model, @NonNull List<Message> messages) {
        BufferedReader reader = null;
        try {
            KimiClient kimiClient = (KimiClient)SpringUtil.getBean("kimiClient");
            String apiKey = kimiClient.getApiKey();
            /**发起http请求*/
            //准备请求体
            String requestBody = new JSONObject()
                    .putOpt("model", model)
                    .putOpt("messages", messages)
                    .putOpt("stream", true)
                    .toString();
            //准备请求头
            Map<String, String > heads = new HashMap<>();
            // 使用json发送请求，下面的是必须的
            heads.put("Authorization", "Bearer " + apiKey);
            //发送请求
            HttpResponse response = HttpRequest.post(CHAT_COMPLETION_URL)
                    .headerMap(heads, false)
                    .body(requestBody)
                    .timeout(5 * 60 * 1000)
                    .execute();
            reader = new BufferedReader(new StringReader(response.body()));
            String line;
            AtomicReference<String> result = new AtomicReference<>("");
            while ((line = reader.readLine()) != null) {
                if (StrUtil.isBlank(line)) {
                    continue;
                }
                if (JSONUtil.isTypeJSON(line)) {
                    Optional.of(JSONUtil.parseObj(line))
                            .map(x -> x.getJSONObject("error"))
                            .map(x -> x.getStr("message"))
                            .ifPresent(x -> {
                                throw new RuntimeException(x);
                            });
                }
                //结束判断
                line = StrUtil.replace(line, "data: ", StrUtil.EMPTY);
                if (StrUtil.equals("[DONE]", line) || !JSONUtil.isTypeJSON(line)) {
                    return result.get();
                }
                //获取内容
                Optional.of(JSONUtil.parseObj(line))
                        .map(x -> x.getJSONArray("choices"))
                        .filter(CollUtil::isNotEmpty)
                        .map(x -> (JSONObject) x.get(0))
                        .map(x -> x.getJSONObject("delta"))
                        .map(x -> x.getStr("content"))
                        .ifPresent(x -> {
                            result.set(result.get() + x);
                        });
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            if (reader != null){
                reader.close();
            }
        }

        throw new RuntimeException("ai无回复");
    }

    @SneakyThrows
    public static String chat(@NonNull String model, @NonNull List<Message> messages) {
        //准备请求体
        String requestBody = new JSONObject()
                .putOpt("model", model)
                .putOpt("messages", messages)
                .putOpt("stream", true)
                .toString();
        //准备请求头
        Map<String, String > heads = new HashMap<>();
        // 使用json发送请求，下面的是必须的
        heads.put("Authorization", "Bearer " + API_KEY);
        //发送请求
        System.out.println("发起请求:"+LocalDateTimeUtil.now());
        HttpRequest  request = HttpRequest.post(CHAT_COMPLETION_URL)
                .headerMap(heads, false)
                .body(requestBody)
                .timeout(5 * 60 * 1000);
        HttpResponse response = request.execute();
        String result = "";
        System.out.println("开获取响应:"+LocalDateTimeUtil.now());
        try (InputStream inputStream = response.bodyStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {

            String line;
            while ((line = reader.readLine()) != null) {
                // 逐行处理数据
                System.out.println(line);
                result=result+line;
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /*@SneakyThrows
    public static String chat(@NonNull String model, @NonNull List<Message> messages) {
        //准备请求体
        String requestBody = new JSONObject()
                .putOpt("model", model)
                .putOpt("messages", messages)
                .putOpt("stream", true)
                .toString();
        //准备请求头
        Map<String, String > heads = new HashMap<>();
        // 使用json发送请求，下面的是必须的
        heads.put("Authorization", "Bearer " + API_KEY);
        //发送请求
        HttpResponse response = HttpRequest.post(CHAT_COMPLETION_URL)
                .headerMap(heads, false)
                .body(requestBody)
                .timeout(5 * 60 * 1000)
                .execute();
        BufferedReader reader = new BufferedReader(new StringReader(response.body()));
        String line;
        AtomicReference<String> result = new AtomicReference<>("");
        while ((line = reader.readLine()) != null) {
            if (StrUtil.isBlank(line)) {
                continue;
            }
            if (JSONUtil.isTypeJSON(line)) {
                Optional.of(JSONUtil.parseObj(line))
                        .map(x -> x.getJSONObject("error"))
                        .map(x -> x.getStr("message"))
                        .ifPresent(x -> {
                            throw new RuntimeException(x);
                        });
            }
            //结束判断
            line = StrUtil.replace(line, "data: ", StrUtil.EMPTY);
            if (StrUtil.equals("[DONE]", line) || !JSONUtil.isTypeJSON(line)) {
                return result.get();
            }
            //获取内容
            Optional.of(JSONUtil.parseObj(line))
                    .map(x -> x.getJSONArray("choices"))
                    .filter(CollUtil::isNotEmpty)
                    .map(x -> (JSONObject) x.get(0))
                    .map(x -> x.getJSONObject("delta"))
                    .map(x -> x.getStr("content"))
                    .ifPresent(x -> {
                        result.set(result.get() + x);
                    });
        }
        throw new RuntimeException("ai无回复");
    }*/

    private static HttpRequest getCommonRequest(@NonNull String url) {
        KimiClient kimiClient = (KimiClient) SpringUtil.getBean("kimiClient");
        String apiKey = kimiClient.getApiKey();
        return HttpRequest.of(url).header(Header.AUTHORIZATION, "Bearer " + apiKey);
    }

}
